home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
admin
/
linuxcon.000
/
linuxcon
/
linuxconf-1.6
/
netconf
/
ipfw.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-06-12
|
6KB
|
275 lines
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/icmp.h>
#include <linux/if.h>
#include <linux/ip_fw.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include "netconf.h"
#include "../misc/misc.h"
#ifndef IP_FW_POLICY_IN
/* These are just here so it compiles */
#define IP_FW_POLICY_IN 0
#define IP_FW_FLUSH_IN 1
#define IP_FW_APPEND_IN 2
#define IP_FW_POLICY_OUT 3
#define IP_FW_FLUSH_OUT 4
#define FIREWALL_NONE
#endif
static int sockfd = -1;
int ipfw_append (
int doit,
SSTRING *collect,
int command,
struct ip_fw &b)
{
int ret = 0;
if (collect != NULL){
/* #Specification: firewall / formatting output
While programming the firewall, we compose in a string
the same format as will be created by the kernel in one
of the file /proc/net/ip_input or /proc/net/ip_forward.
So it become possible to compare this with the current
content of those file and tell if something as to be done.
*/
#ifndef FIREWALL_NONE
char buffer[300];
int len=sprintf(buffer,"%08lX/%08lX->%08lX/%08lX %.16s %08lX %X "
,ntohl(b.fw_src.s_addr),ntohl(b.fw_smsk.s_addr)
,ntohl(b.fw_dst.s_addr),ntohl(b.fw_dmsk.s_addr)
,(b.fw_vianame)[0] ? b.fw_vianame : "-"
,ntohl(b.fw_via.s_addr),b.fw_flg);
len+=sprintf(buffer+len,"%u %u %-9lu %-9lu"
,b.fw_nsp,b.fw_ndp, b.fw_pcnt,b.fw_bcnt);
for (int p = 0; p < IP_FW_MAX_PORTS; p++)
len+=sprintf(buffer+len, " %u", b.fw_pts[p]);
sprintf(buffer+len, " A%02X X%02X\n", b.fw_tosand, b.fw_tosxor);
collect->append (buffer);
#endif
}
if (doit){
ret = setsockopt (sockfd, IPPROTO_IP, command
,&b,sizeof(struct ip_fw));
if (ret != 0){
xconf_error ("error append firewall %d(%s)",errno,strerror(errno));
}
}
return ret;
}
int ipfw_flush (
int doit,
SSTRING *,
int command)
{
int ret = 0;
if (doit){
int data = 0;
ret = setsockopt (sockfd, IPPROTO_IP, command,&data,sizeof(data));
if (ret != 0){
xconf_error ("error flush firewall %d(%s)",errno,strerror(errno));
}
}
return ret;
}
int ipfw_policy (
int doit,
SSTRING *collect,
int command,
int policy)
{
int ret = 0;
if (collect != NULL){
char *ctl = NULL;
switch (command){
case IP_FW_POLICY_IN:
ctl = "IP firewall input rules, default %d\n";
break;
case IP_FW_POLICY_OUT:
ctl = "IP firewall output rules, default %d\n";
break;
case IP_FW_POLICY_FWD:
ctl = "IP firewall forward rules, default %d\n";
break;
}
char buf[100];
sprintf(buf,ctl,policy);
collect->append (buf);
}
if (doit){
ret = setsockopt (sockfd, IPPROTO_IP, command,&policy,sizeof(policy));
}
return ret;
}
/*
Initialise the sockfd needed to program the rules
Return -1 if any error.
*/
int ipfw_open ()
{
sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
return sockfd;
}
void ipfw_close()
{
close (sockfd);
sockfd = -1;
}
#ifndef FIREWALL_NONE
/*
Translate and validate an ASCII IP addr.
*/
static int ipfw_a2ip (const char *adr, struct in_addr &ina)
{
int num4[4];
int ret = device_aip24 (adr,num4);
if (ret != -1){
unsigned long ipa = (num4[0] <<24) | (num4[1] << 16)
| (num4[2] << 8) | num4[3];
ina.s_addr = htonl (ipa);
}
return ret;
}
static int ipfw_setrange (
const char *range,
struct ip_fw &bf,
int flag,
int noport,
unsigned short &nb)
{
const char *s = str_skip (range);
if (s[0] != '\0'){
bf.fw_flg |= flag;
bf.fw_pts[noport++] = atoi(s);
s = str_skipdig (s);
s = str_skip (s);
if (*s == ':') s++;
s = str_skip (s);
bf.fw_pts[noport++] = atoi(s);
nb = 2;
}
return noport;
}
static int ipfw_setports (
const char *ports,
struct ip_fw &bf,
unsigned short &nb,
int noport,
const char *proto)
{
while (1){
ports = str_skip (ports);
if (ports[0] == '\0'){
break;
}else{
char word[200];
ports = str_copyword(word,ports);
int port = atoi(word);
struct servent *serv = getservbyname (word,proto);
if (serv != NULL) port = ntohs(serv->s_port);
bf.fw_pts[noport++] = port;
nb++;
}
}
return noport;
}
/*
Return -1 if anything is invalid
*/
int ipfw_baseinit (
const char *iface,
const char *protocol,
const char *ip_src,
const char *msk_src,
const char *sport_range,
const char *sports,
const char *ip_dst,
const char *msk_dst,
const char *dport_range,
const char *dports,
struct ip_fw &bf)
{
memset (&bf,0,sizeof(bf));
int ret = ipfw_a2ip (ip_src,bf.fw_src);
ret |= ipfw_a2ip (msk_src,bf.fw_smsk);
bf.fw_src.s_addr &= bf.fw_smsk.s_addr;
ret |= ipfw_a2ip (ip_dst,bf.fw_dst);
ret |= ipfw_a2ip (msk_dst,bf.fw_dmsk);
bf.fw_dst.s_addr &= bf.fw_dmsk.s_addr;
/* #Specification: firewall / iface / assumption
We assume that all network device do begin with a letter.
This way we differentiate IP number for interface from name
*/
if (isalpha(iface[0])){
strcpy (bf.fw_vianame,iface);
}else{
ret |= ipfw_a2ip (iface,bf.fw_via);
}
if (stricmp(protocol,"all")==0){
bf.fw_flg = IP_FW_F_ALL;
}else if (stricmp(protocol,"tcp")==0){
bf.fw_flg = IP_FW_F_TCP;
}else if (stricmp(protocol,"udp")==0){
bf.fw_flg = IP_FW_F_UDP;
}else if (stricmp(protocol,"icmp")==0){
bf.fw_flg = IP_FW_F_ICMP;
}else{
ret = -1;
}
int noport = ipfw_setrange (sport_range,bf,IP_FW_F_SRNG,0,bf.fw_nsp);
noport = ipfw_setports (sports,bf,bf.fw_nsp,noport,protocol);
noport = ipfw_setrange (dport_range,bf,IP_FW_F_DRNG,noport,bf.fw_ndp);
ipfw_setports (dports,bf,bf.fw_ndp,noport,protocol);
bf.fw_tosand = 0xFF;
bf.fw_tosxor = 0x00;
bf.fw_flg |= IP_FW_F_ACCEPT;
return ret;
}
#else
int ipfw_baseinit (
const char *,
const char *,
const char *,
const char *,
const char *,
const char *,
const char *,
const char *,
const char *,
const char *,
struct ip_fw &)
{
return -1;
}
#endif